package ar.edu.caece.compiler.grammar.factories;

import ar.edu.caece.compiler.grammar.AbstractTokenVisitorFactory;
import ar.edu.caece.compiler.grammar.Recognizer;
import ar.edu.caece.compiler.grammar.TokenRecognizer;
import ar.edu.caece.compiler.grammar.TokenVisitor;
import ar.edu.caece.compiler.grammar.attributes.Attribute;
import ar.edu.caece.compiler.grammar.attributes.tree.AttributeTreeNode;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeMostrar;
import ar.edu.caece.compiler.grammar.nonterminals.EXPR;
import ar.edu.caece.compiler.grammar.nonterminals.TEXTO2;
import ar.edu.caece.compiler.grammar.nonterminals.TEXTOA;


public class TEXTO2Factory extends AbstractTokenVisitorFactory {

	private static TEXTO2Factory INSTANCE;
	
	public static TEXTO2Factory getInstance() throws Exception {
		if(INSTANCE==null) INSTANCE = new TEXTO2Factory();
		return INSTANCE;
	}
	
	private EXPRFactory exprFactory;
	private TEXTOAFactory textoaFactory;
	private TokenVisitor parseEXPR;
	private TokenVisitor parseTEXTOA;
	
	private Initializer initializer = new Initializer() {
		
		@Override
		public void init() throws Exception {
			initializer = NoOperationInitializer.getInstance();
			exprFactory = EXPRFactory.getInstance();
			textoaFactory = TEXTOAFactory.getInstance();
			parseTEXTOA = textoaFactory.makeVisitor();
			parseEXPR = exprFactory.makeVisitor();
		}
	};
	
	private TEXTO2Factory() throws Exception {

	}
	
	@Override
	public TokenVisitor makeChainedVisitor(
			final TokenVisitor siguiente) throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador)
					throws Exception {
				TokenVisitor parseEXPR2 = exprFactory.makeChainedVisitor(siguiente);
				parseEXPR2.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				Recognizer result = llamador.execute(parseEXPR2);
				if(result instanceof EXPR) {
					parseEXPR.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
					parseTEXTOA.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
					
					NodeMostrar nodeMostrar = (NodeMostrar) getAttribute(Attribute.ARBOL_HEREDADO);
							
					EXPR expr = (EXPR) result;
					nodeMostrar.addMostrarNode((AttributeTreeNode) expr.getAttribute(Attribute.ARBOL_SINTETIZADO));

					parseTEXTOA.addInheretedAttribute(Attribute.ARBOL_HEREDADO, nodeMostrar);
					TEXTOA textoa = (TEXTOA) nextToken().execute(parseTEXTOA);
					TEXTO2 texto2 = new TEXTO2 (expr, textoa);
					
					texto2.addAttribute(Attribute.ARBOL_SINTETIZADO, texto2.getAttribute(Attribute.ARBOL_SINTETIZADO));
					return texto2;			} 
				else {
					return result;
				}
			}
			
		};
	
	}
	@Override
	public TokenVisitor makeVisitor() throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador) throws Exception {
				
				parseEXPR.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parseTEXTOA.addInheretedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				
				NodeMostrar nodeMostrar = (NodeMostrar) getAttribute(Attribute.ARBOL_HEREDADO);
						
				EXPR expr = (EXPR) llamador.execute(parseEXPR);
				nodeMostrar.addMostrarNode((AttributeTreeNode) expr.getAttribute(Attribute.ARBOL_SINTETIZADO));

				parseTEXTOA.addInheretedAttribute(Attribute.ARBOL_HEREDADO, nodeMostrar);
				TEXTOA textoa = (TEXTOA) nextToken().execute(parseTEXTOA);
				TEXTO2 texto2 = new TEXTO2 (expr, textoa);
				
				texto2.addAttribute(Attribute.ARBOL_SINTETIZADO, texto2.getAttribute(Attribute.ARBOL_SINTETIZADO));
				return texto2;
			}
		};
	}
	
	
}
